/*
 * Copyright:  2018 smarabbit studio.
 *
 *  Licensed under the Confluent Community License; you may not use this file
 *  except in compliance with the License.  You may obtain a copy of the License at
 *
 *  http://www.confluent.io/confluent-community-license
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 *  WARRANTIES OF ANY KIND, either express or implied.  See the License for the
 *  specific language governing permissions and limitations under the License.
 *
 *  @作   者： 黄开晖 (117227773@qq.com)
 *  @日   期:  2021年9月4日
 */
package com.massyframework.beanskin.runtime.nativelib;

import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.List;

import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import com.massyframework.beanskin.license.License;
import com.massyframework.beanskin.util.IOUtils;

/**
 * license.xml解析器
 * @author huangkh
 */
public class LicensesXmlParser extends XmlParser {
	
	private static final String CUSTOMER      = "customer"; 
	private static final String CUSTOMERID    = "id";
	
	private static final String LICENSE       = "license";
	
	private static final String GROUPID       = "groupId";
	private static final String MODULEID      = "moduleId";
	private static final String VERSIONRANGE  = "version-range";

	private static final String EXPIREDATE    = "expire-date";
	
	private static final String PARAMETERS    = "parameters";
	private static final String PARAMETER     = "parameter";
	private static final String PARAM_NAME    = "name";
	private static final String PARAM_VALUE   = "value";
	private static final String SIGNATURE     = "signature";
	private static final String X509CERT      = "x509cert";
	/**
	 * 
	 */
	public LicensesXmlParser() {

	}
	
	public List<License> parseFrom(File xmlFile) throws Exception {
		this.validateXml(xmlFile);
		
		List<License> result = new ArrayList<>();
		InputStream is = null;
		try {			
			is = new FileInputStream(xmlFile);
			Document document = this.createDocument(is);
			this.doParse(document, result);
		}finally {
			IOUtils.close(is);
		}
		
		return result;
	}
	
	/**
	 * 执行解析
	 * @param doc
	 * @param builder
	 */
	protected void doParse(Document doc, List<License> licenses) {
		NodeList nodes = doc.getElementsByTagName(CUSTOMER);
		String customerId = this.doParserCustomerId(nodes.item(0));
		
		nodes = doc.getElementsByTagName(LICENSE);
		int size = nodes.getLength();
		List<License.Builder> builders = new ArrayList<>();
		for (int i=0; i<size; i++) {
			Node node = nodes.item(i);
			
			String name = node.getNodeName();
			if (LICENSE.equals(name)) {
				License.Builder builder = License.newBuilder();
				builder.customerId(Long.parseLong(customerId));
				this.doParseLicense(node, builder);
				builders.add(builder);
			}
			
			
		}
		
		nodes = doc.getElementsByTagName(X509CERT);
		String x509cert = this.getTextContent(nodes.item(0));
		
		for (License.Builder builder: builders) {
			builder.x509cert(x509cert);
			licenses.add(builder.build());
		}
	}
	
	
	protected String doParserCustomerId(Node node) {
		NodeList nodes = node.getChildNodes();
		int size = nodes.getLength();
		
		for (int i=0; i<size; i++) {
			Node child = nodes.item(i);
			
			String name = child.getNodeName();
			if (name.equals(CUSTOMERID)) {
				return this.getTextContent(child);
			}
		}
		
		return null;
	}
	
	/**
	 * 解析许可
	 * @param node 
	 * @param builder
	 */
	protected void doParseLicense(Node node, License.Builder builder) {
		NodeList nodes = node.getChildNodes();
		int size = nodes.getLength();
		
		for (int i=0; i<size; i++) {
			Node child = nodes.item(i);
			String nodeName = child.getNodeName();
			
			if (GROUPID.equals(nodeName)) {
				builder.groupId(this.getTextContent(child));
				continue;
			}
			
			if (MODULEID.equals(nodeName)) {
				builder.moduleId(this.getTextContent(child));
				continue;
			}
			
			if (VERSIONRANGE.equals(nodeName)) {
				builder.versionRange(this.getTextContent(child));
				continue;
			}
						
			if (EXPIREDATE.equals(nodeName)){
				builder.expireDate(LocalDate.parse(this.getTextContent(child)));
				continue;
			}
			
			if (PARAMETERS.equals(nodeName)) {
				this.doParseParameters(child.getChildNodes(), builder);
				continue;
			}
			
			if (SIGNATURE.equals(nodeName)) {
				builder.signature(this.getTextContent(child));
				continue;
			}
		}
	}
	
	/**
	 * 解析参数集
	 * @param nodes
	 * @param builder
	 */
	protected void doParseParameters(NodeList nodes, License.Builder builder) {
		int size = nodes.getLength();
		for (int i=0; i<size; i++) {
			Node node = nodes.item(i);
			if (PARAMETER.equals(node.getNodeName())) {
				this.doParseParameter(node, builder);
			}
		}
	}
	
	/**
	 * 解析参数
	 * @param node
	 * @param builder
	 */
	protected void doParseParameter(Node node, License.Builder builder) {
		String name = null;
		String value = null;
		
		Node nameNode = node.getAttributes().getNamedItem(PARAM_NAME);
		if (nameNode != null) {
			name = this.getTextContent(nameNode);
		}
		
		Node valueNode = node.getAttributes().getNamedItem(PARAM_VALUE);
		if (valueNode != null) {
			value = this.getTextContent(valueNode);
		}
		
		builder.addParameter(name, value);
	}

	@Override
	protected String getResouceNameWithXmlSchemaFile() {
		return "com/massyframework/beanskin/config/licenses-2.0.0.xsd";
	}
}
